<!DOCTYPE html>
<html lang="zh_cn">
<head>
          <title>来玩魔王的咚</title>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <meta charset="utf-8" />
        <!-- twitter card metadata -->
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="/images/mowang.png">
<meta name="twitter:site" content="">
<meta name="twitter:title" content="awk命令和Zabbix自定义监控项">
<meta name="twitter:description" content="<p>awk命令基本用法，awk自定义变量，awk进阶内容。zabbix自定义参数监控</p>">
        <!-- OG Tags -->
<meta property="og:url" content="/awk-and-zabbix-user-parameter-item.html"/>
<meta property="og:title" content="来玩魔王的咚 | awk命令和Zabbix自定义监控项" />
<meta property="og:description" content="<p>awk命令基本用法，awk自定义变量，awk进阶内容。zabbix自定义参数监控</p>" />
        <!-- favicon -->
        <link rel="icon" type="image/png" href="/images/mowang.png">
        <!-- moment.js for date formatting -->
        <script src="/theme/js/moment.js"></script>
        <!-- css -->
        <link rel="stylesheet" type="text/css" href="/theme/css/main.css" />
        <!-- 左边的menu，如果页面高度不够，就跟着滚动，否则文章分类显示不全 -->
        <link rel="stylesheet" type="text/css" href="/theme/css/mycss/menu.css" />
		<script>
			
                /*! grunt-grunticon Stylesheet Loader - v2.1.2 | https://github.com/filamentgroup/grunticon | (c) 2015 Scott Jehl, Filament Group, Inc. | MIT license. */
    
    (function(e){function t(t,n,r,o){"use strict";function a(){for(var e,n=0;u.length>n;n++)u[n].href&&u[n].href.indexOf(t)>-1&&(e=!0);e?i.media=r||"all":setTimeout(a)}var i=e.document.createElement("link"),l=n||e.document.getElementsByTagName("script")[0],u=e.document.styleSheets;return i.rel="stylesheet",i.href=t,i.media="only x",i.onload=o||null,l.parentNode.insertBefore(i,l),a(),i}var n=function(r,o){"use strict";if(r&&3===r.length){var a=e.navigator,i=e.Image,l=!(!document.createElementNS||!document.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect||!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image","1.1")||e.opera&&-1===a.userAgent.indexOf("Chrome")||-1!==a.userAgent.indexOf("Series40")),u=new i;u.onerror=function(){n.method="png",n.href=r[2],t(r[2])},u.onload=function(){var e=1===u.width&&1===u.height,a=r[e&&l?0:e?1:2];n.method=e&&l?"svg":e?"datapng":"png",n.href=a,t(a,null,null,o)},u.src="",document.documentElement.className+=" grunticon"}};n.loadCSS=t,e.grunticon=n})(this);(function(e,t){"use strict";var n=t.document,r="grunticon:",o=function(e){if(n.attachEvent?"complete"===n.readyState:"loading"!==n.readyState)e();else{var t=!1;n.addEventListener("readystatechange",function(){t||(t=!0,e())},!1)}},a=function(e){return t.document.querySelector('link[href$="'+e+'"]')},c=function(e){var t,n,o,a,c,i,u={};if(t=e.sheet,!t)return u;n=t.cssRules?t.cssRules:t.rules;for(var l=0;n.length>l;l++)o=n[l].cssText,a=r+n[l].selectorText,c=o.split(");")[0].match(/US\-ASCII\,([^"']+)/),c&&c[1]&&(i=decodeURIComponent(c[1]),u[a]=i);return u},i=function(e){var t,o,a;o="data-grunticon-embed";for(var c in e)if(a=c.slice(r.length),t=n.querySelectorAll(a+"["+o+"]"),t.length)for(var i=0;t.length>i;i++)t[i].innerHTML=e[c],t[i].style.backgroundImage="none",t[i].removeAttribute(o);return t},u=function(t){"svg"===e.method&&o(function(){i(c(a(e.href))),"function"==typeof t&&t()})};e.embedIcons=i,e.getCSS=a,e.getIcons=c,e.ready=o,e.svgLoadedCallback=u,e.embedSVG=u})(grunticon,this);
                
                grunticon(["/theme/css/icons.data.svg.css", "/theme/css/icons.data.png.css", "/theme/css/icons.fallback.css"]);
            </script>
        <noscript><link href="/theme/css/icons.fallback.css" rel="stylesheet"></noscript>
        <!-- menu toggle javascript -->
        <script type="text/javascript">
            document.addEventListener("DOMContentLoaded", initMenu);
            
            function initMenu(){
                var menu = document.getElementById("menu");
                var menulink = document.getElementById("menu-link");
                menulink.addEventListener("click", function toggleMenu(){
                        window.event.preventDefault();
                        menulink.classList.toggle('active');
                        menu.classList.toggle('active');              
                    });
            };
        </script>
        <!-- 不蒜子 -->
        <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>

    <meta name="description" content="<p>awk命令基本用法，awk自定义变量，awk进阶内容。zabbix自定义参数监控</p>" />

    <meta name="tags" content="awk" />
    <meta name="tags" content="zabbix" />
  <!-- 替换部分base的样式，看文章时，要再宽一点，右边有很多空间可以撑开 -->
  <link rel="stylesheet" type="text/css" href="/theme/css/mycss/article.css" />

</head>
<body>
    <div role="banner" id="masthead">
        <header>
            <a href="/"><img src="/images/mowang.png" alt="McManus Logo"></a>
                <h1>来玩魔王的咚@骑士救兵</h1>
            <a href="#menu" id="menu-link">more stuff</a>
            <nav id="menu">
                <ul>
                        <li><a href="/tags">tags</a></li>
                            <li><a href="/category/cloud.html">Cloud</a></li>
                            <li><a href="/category/docker.html">Docker</a></li>
                            <li><a href="/category/go.html">Go</a></li>
                            <li><a href="/category/linux.html">Linux</a></li>
                            <li><a href="/category/python.html">Python</a></li>
                            <li><a href="/category/xue-xi-bi-ji.html">学习笔记</a></li>
                            <li class="active"><a href="/category/yun-wei-zi-dong-hua.html">运维自动化</a></li>
                </ul>
            </nav>
        </header>
    </div>
        <div class="page" role="main">
  <div class="article" role="article">
    <article>
        <footer>
            <a name="top"></a>
            <p>
              <time datetime=" 2020-07-05 20:20:00+08:00">
                <script>document.write(moment('2020-07-05 20:20:00+08:00').format('LL'));</script>
              </time>
              ~
              <time datetime=" 2020-07-05 20:20:00+08:00">
                <script>document.write(moment('2020-07-05 20:20:00+08:00').format('LL'));</script>
              </time>
            </p>
        </footer>
        <header>
          <h2>
            awk命令和Zabbix自定义监控项
          </h2>
        </header>
      <div class="content">
         <div class="toc">
<ul>
<li><a href="#awk-ming-ling">awk 命令</a><ul>
<li><a href="#shu-chu-wen-jian-pi-pei-xing-de-te-ding-zi-duan">输出文件匹配行的特定字段</a></li>
<li><a href="#nei-zhi-bian-liang">内置变量</a></li>
<li><a href="#fen-ge-fu">分隔符</a></li>
<li><a href="#ge-shi-hua-shu-chu-printf">格式化输出printf</a></li>
<li><a href="#begin-he-end-mo-kuai">BEGIN 和 END 模块</a></li>
</ul>
</li>
<li><a href="#awk-zi-ding-yi-bian-liang">awk自定义变量</a><ul>
<li><a href="#ding-yi-zai-hou-mian">定义在后面</a></li>
<li><a href="#zai-begin-kuai-zhong-ding-yi">在BEGIN块中定义</a></li>
<li><a href="#shi-yong-v-xuan-xiang">使用 -v 选项</a></li>
<li><a href="#da-yin-huan-jing-bian-liang">打印环境变量</a></li>
<li><a href="#yin-yong-ming-ling-xing-ding-yi-de-bian-liang">引用命令行定义的变量</a></li>
</ul>
</li>
<li><a href="#awk-jin-jie">awk 进阶</a><ul>
<li><a href="#tiao-jian-xian-zhi">条件限制</a></li>
<li><a href="#tiao-jian-yu-ju">条件语句</a></li>
<li><a href="#zheng-ze-pi-pei">正则匹配</a></li>
<li><a href="#da-yin-jiu-jiu-cheng-fa-biao">打印九九乘法表</a></li>
</ul>
</li>
<li><a href="#zabbix-zi-ding-yi-can-shu-jian-kong-xiang">Zabbix 自定义参数（监控项）</a><ul>
<li><a href="#pei-zhi-wen-jian">配置文件</a></li>
<li><a href="#yu-fa">语法</a></li>
<li><a href="#tiao-shi-bu-zhou">调试步骤</a></li>
<li><a href="#dai-can-shu-de-yong-fa">带参数的用法</a></li>
<li><a href="#shi-li">示例</a></li>
<li><a href="#systemrun">system.run</a></li>
</ul>
</li>
</ul>
</div>
<p>awk功能很强大，如果只是用来实现zabbix自定义监控项的话，基础的内容就够了。这篇对awk的学习不只限于实现zabbix的监控，而是稍微深入了一些。  </p>
<h3 id="awk-ming-ling"><a class="toclink" href="#awk-ming-ling">awk 命令</a></h3>
<p>awk是一种处理文本文件的语言，是一个强大的文本分析公具。 
awk处理文本和数据的方式：逐行读入文本，寻找匹配特定模式的行，然后进行操作。  </p>
<h4 id="shu-chu-wen-jian-pi-pei-xing-de-te-ding-zi-duan"><a class="toclink" href="#shu-chu-wen-jian-pi-pei-xing-de-te-ding-zi-duan">输出文件匹配行的特定字段</a></h4>
<p>功能很强大，所以有很多用处。这里我主要关注下面这样的场景:<br>
逐行读入文本，按规则匹配特定的行，以空格为默认分隔符将每行切片，输出其中特定的某个切片（切开的部分可以进行各种分析处理，这里就是要输出其中以段）<br>
举例如下:</p>
<div class="highlight"><pre><span></span><code>$ cat /etc/hosts
<span class="m">127</span>.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
$ awk <span class="s1">&#39;/local/ {print $1}&#39;</span> /etc/hosts
<span class="m">127</span>.0.0.1
::1
$ 
</code></pre></div>

<p>这种方法很适合用来做zabbix的自定义key的监控。比如从free命令中，提取出内存的使用量：</p>
<div class="highlight"><pre><span></span><code>$ free
              total        used        free      shared  buff/cache   available
Mem:        <span class="m">1855432</span>      <span class="m">320688</span>     <span class="m">1238808</span>       <span class="m">10612</span>      <span class="m">295936</span>     <span class="m">1495432</span>
Swap:       <span class="m">2093052</span>           <span class="m">0</span>     <span class="m">2093052</span>
$ free <span class="p">|</span> awk <span class="s1">&#39;/^Mem:/ {print $3}&#39;</span>
<span class="m">320688</span>
$ 
</code></pre></div>

<p><strong>grep命令</strong><br>
同样的效果，也可以通过grep命令来把需要的行过滤出来，然后还得借助cut命令来进行列切割。<br>
但是使用awk的话就一步搞定了。  </p>
<h4 id="nei-zhi-bian-liang"><a class="toclink" href="#nei-zhi-bian-liang">内置变量</a></h4>
<p>内置变量先列出来，后面会用到其中一些。<br>
<strong>awk内置变量：</strong></p>
<ul>
<li>ARGC: 命令行参数个数</li>
<li>ARGV: 命令行参数排列</li>
<li>ENVIRON: 支持队列中系统环境变量的使用</li>
<li>FILENAME: awk浏览的文件名</li>
<li>FNR: 浏览文件的记录数</li>
<li>FS: 设置输入域分隔符，等价于命令行 -F选项</li>
<li>IGNORECASE: 如果把这个变量设为1，则正则表达式忽略大小写</li>
<li>NF: 浏览记录的域的个数</li>
<li>NR: 已读的记录数</li>
<li>OFS: 输出域分隔符</li>
<li>ORS: 输出记录分隔符</li>
<li>RS: 控制记录分隔符</li>
<li>$0: 变量是指整条记录</li>
<li>$1: 表示当前行的第一个域,$2表示当前行的第二个域,......以此类推</li>
<li>$NF: 既然 NF是列的总数，那么$NF就是最后一列的值</li>
<li>$NF-1: 这个是倒数第二列，其他以此类推</li>
</ul>
<p>上面这些变量，有些是直接来使用的。比如$1，$NF，后面的例子中会用到，也比较好理解。<br>
还有些是用来改变awk行为的，需要对变量进行设置，这个需要会为变量赋值，有多种方式可以实现。<br>
比如FS，是用来指定分隔符的，默认的分隔符是空白符，但是可以指定。这就需要自己定义FS的值。不过分隔符还提供了一个 -F 选项来定义。所以也可以在命令行选项中设置。<br>
但是其他一些变量需要指定，但又没有提供别的方法的话，就只能用过为变量赋值来实现了。<br>
分隔符和为变量赋值的方式在后面会展开，为变量赋值参考自定义变量的内容。  </p>
<h4 id="fen-ge-fu"><a class="toclink" href="#fen-ge-fu">分隔符</a></h4>
<p>默认awk是以空白符来做分隔的。使用 -F 选项可以自定义分隔符：</p>
<div class="highlight"><pre><span></span><code>$ grep -e <span class="s2">&quot;^root&quot;</span> /etc/passwd
root:x:0:0:root:/root:/bin/bash
$ awk -F: <span class="s1">&#39;/^root/ {print $1,$NF}&#39;</span> /etc/passwd
root /bin/bash
$ 
</code></pre></div>

<p>这里将分隔符指定为冒号。  </p>
<h5 id="duo-fen-ge-fu"><a class="toclink" href="#duo-fen-ge-fu">多分隔符</a></h5>
<p>默认的也是多分隔符的情况，空格、制表符等都会被识别。自己要指定多个分隔符，则是用中括号把需要识别的分隔符都括起来：</p>
<div class="highlight"><pre><span></span><code>$ <span class="nb">echo</span> <span class="s2">&quot;a-b_c=d-E_F=G&quot;</span> <span class="p">|</span> awk -F<span class="o">[</span>-_<span class="o">=]</span> <span class="s1">&#39;{print $1,$2,$3,$4,$5,$6,$7}&#39;</span>
a b c d E F G
$ 
</code></pre></div>

<h5 id="guo-lv-lian-xu-de-fen-ge-fu"><a class="toclink" href="#guo-lv-lian-xu-de-fen-ge-fu">过滤连续的分隔符</a></h5>
<p>-F 选项也是支持正则表达式的，中括号就是正则表达式字符集合的意思。但是如果这时遇到连续的分隔符，就会有问题。<br>
下面使用逗号和空格作为分隔符，并且每次都连续出现：</p>
<div class="highlight"><pre><span></span><code>$ <span class="nb">echo</span> <span class="s2">&quot;a,,b  c&quot;</span> <span class="p">|</span> awk -F<span class="s1">&#39;[ ,]&#39;</span> <span class="s1">&#39;{print $1&quot;-&quot;$2&quot;-&quot;$3}&#39;</span> 
a--b
$ 
</code></pre></div>

<p>正则表达式中匹配一次或多次，使用加号后，就可以了：</p>
<div class="highlight"><pre><span></span><code>$ <span class="nb">echo</span> <span class="s2">&quot;a,,b  c&quot;</span> <span class="p">|</span> awk -F<span class="s1">&#39;[ ,]+&#39;</span> <span class="s1">&#39;{print $1&quot;-&quot;$2&quot;-&quot;$3}&#39;</span>
a-b-c
$ 
</code></pre></div>

<h5 id="te-shu-zi-fu-fen-ge-fu"><a class="toclink" href="#te-shu-zi-fu-fen-ge-fu">特殊字符分隔符</a></h5>
<p>特殊字符应该就是这些： <code>$、^、*、(、)、[、]、?、.、|</code><br>
单独作为分隔符并没有问题：</p>
<div class="highlight"><pre><span></span><code>$ <span class="nb">echo</span> <span class="s1">&#39;1a$1b$1c&#39;</span> <span class="p">|</span> awk -F<span class="s1">&#39;$&#39;</span> <span class="s1">&#39;{print $1&quot;-&quot;$2&quot;-&quot;$3}&#39;</span>   
1a-1b-1c
$ 
</code></pre></div>

<p>如果指定多个字符作为一个整体作为一个分隔符，就会有问题，需要转义。<br>
比如这里要将 $1 作为分隔符：</p>
<div class="highlight"><pre><span></span><code>$ <span class="nb">echo</span> <span class="s1">&#39;1a$1b$1c&#39;</span> <span class="p">|</span> awk -F<span class="s1">&#39;$1&#39;</span> <span class="s1">&#39;{print $1&quot;-&quot;$2&quot;-&quot;$3}&#39;</span>
1a<span class="nv">$1</span>b<span class="nv">$1</span>c--
$ <span class="nb">echo</span> <span class="s1">&#39;1a$1b$1c&#39;</span> <span class="p">|</span> awk -F<span class="s1">&#39;\\$1&#39;</span> <span class="s1">&#39;{print $1&quot;-&quot;$2&quot;-&quot;$3}&#39;</span>
1a-b-c
$ 
</code></pre></div>

<p>再来个多个特殊字符组合的:</p>
<div class="highlight"><pre><span></span><code>$ <span class="nb">echo</span> <span class="s1">&#39;a$|b$|c&#39;</span> <span class="p">|</span> awk -F<span class="s1">&#39;\\$\\|&#39;</span> <span class="s1">&#39;{print $1&quot;-&quot;$2&quot;-&quot;$3}&#39;</span>
a-b-c
$ 
</code></pre></div>

<h5 id="mo-ren-fen-ge-fu"><a class="toclink" href="#mo-ren-fen-ge-fu">默认分隔符</a></h5>
<p>默认就是空白符作为分隔符，并且能够识别连续的空白符。默认分隔符就是下面的这个正则表达式：</p>
<div class="highlight"><pre><span></span><code><span class="nv">FS</span><span class="o">=</span><span class="s2">&quot;[[:space:]+]&quot;</span> 
</code></pre></div>

<p>看上面的内置变量，FS和-F选项是等价的。  </p>
<h4 id="ge-shi-hua-shu-chu-printf"><a class="toclink" href="#ge-shi-hua-shu-chu-printf">格式化输出printf</a></h4>
<p>除了用print，还可以用printf做格式化输出。这里就给出一个例子，关于printf格式化输出，需要的话再去参考下C语言的printf的功能把。<br>
一般都用print输出：</p>
<div class="highlight"><pre><span></span><code>$ awk -F: <span class="s1">&#39;{print &quot;filename:&quot; FILENAME &quot;,linenumber:&quot; NR &quot;,columns:&quot; NF &quot;,linecontent:&quot;$0}&#39;</span> /etc/passwd     
filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash
filename:/etc/passwd,linenumber:2,columns:7,linecontent:bin:x:1:1:bin:/bin:/sbin/nologin
filename:/etc/passwd,linenumber:3,columns:7,linecontent:daemon:x:2:2:daemon:/sbin:/sbin/nologin
</code></pre></div>

<p>对比下用printf格式化输出后的效果：</p>
<div class="highlight"><pre><span></span><code>$ awk -F: <span class="s1">&#39;{printf (&quot;filename:%10s, linenumber:%3s,column:%3s,content:%3f\n&quot;,FILENAME,NR,NF,$0)}&#39;</span> /etc/passwd
filename:/etc/passwd, linenumber:  <span class="m">1</span>,column:  <span class="m">7</span>,content:0.000000
filename:/etc/passwd, linenumber:  <span class="m">2</span>,column:  <span class="m">7</span>,content:0.000000
filename:/etc/passwd, linenumber:  <span class="m">3</span>,column:  <span class="m">7</span>,content:0.000000
</code></pre></div>

<h4 id="begin-he-end-mo-kuai"><a class="toclink" href="#begin-he-end-mo-kuai">BEGIN 和 END 模块</a></h4>
<p>通常，对于每个输入行，awk 都会执行一次脚本代码块。<br>
有时，需要在 awk 开始处理输入文件中的文本之前执行初始化代码。这就需要定义一个 BEGIN 块。<br>
另外，还有一个 END 块，用于执行最终计算或打印应该出现在输出流结尾的摘要信息。  </p>
<p><strong>在BEGIN块中定义内置变量</strong><br>
这里在BEGIN块中定义了两个内置变量：</p>
<div class="highlight"><pre><span></span><code>$ <span class="nb">echo</span> <span class="s2">&quot;a,,b   c&quot;</span> <span class="p">|</span> awk <span class="s1">&#39;BEGIN{FS=&quot;[ ,]+&quot;;OFS=&quot;-&quot;}{print $1,$2,$3}&#39;</span> 
a-b-c
$ 
</code></pre></div>

<p>FS是分隔符，OFS是输出字段分隔符。在之前的例子中，不用BEGIN块也是能实现这个效果的。<br>
这里修改的是一个内置变量，但是方法是针对变量的，包括自定义变量。具体参考下一章“awk自定义变量”。  </p>
<p>这里主要挑BEGIN块举例用法。END块可以实现计算统计输出的功能，暂时用不上，略过。  </p>
<h3 id="awk-zi-ding-yi-bian-liang"><a class="toclink" href="#awk-zi-ding-yi-bian-liang">awk自定义变量</a></h3>
<p>除了内置变量，也可以定义自定义变量并使用。这部分内容对于灵活的配置非常有用，而且如果自己写，也会遇到一些坑。  </p>
<h4 id="ding-yi-zai-hou-mian"><a class="toclink" href="#ding-yi-zai-hou-mian">定义在后面</a></h4>
<p><em>这里变量的赋值在发生在BEGIN块执行之后的</em><br>
直接写在后面：</p>
<div class="highlight"><pre><span></span><code>$ <span class="nb">echo</span> <span class="p">|</span> awk <span class="s1">&#39;{print key1,key2}&#39;</span> <span class="nv">key1</span><span class="o">=</span>v1 <span class="nv">key2</span><span class="o">=</span>V2
v1 V2
$ 
</code></pre></div>

<p>这种用法在BEGIN块中是识别不了变量的。BEGIN块的执行在这些变量定义之前。不过还有其他的方法可以用。<br>
另外，这里使用管道作为标准输入。如果是从文件输入的话，文件路径在写最后。  </p>
<h4 id="zai-begin-kuai-zhong-ding-yi"><a class="toclink" href="#zai-begin-kuai-zhong-ding-yi">在BEGIN块中定义</a></h4>
<p><em>这里变量额赋值是在BEGIN块执行的时候</em><br>
在BEGIN块中可以对内置变量赋值，同样的也可以为自定义变量赋值:</p>
<div class="highlight"><pre><span></span><code>$ <span class="nb">echo</span> <span class="p">|</span> awk <span class="s1">&#39;BEGIN{key1=&quot;v1&quot;;key2=&quot;value2&quot;;OFS=&quot;_&quot;}{print key1,key2}&#39;</span> 
v1_value2
$ 
</code></pre></div>

<h4 id="shi-yong-v-xuan-xiang"><a class="toclink" href="#shi-yong-v-xuan-xiang">使用 -v 选项</a></h4>
<p><em>这里变量的赋值是在BEGIN块执行之前</em><br>
这个方法在发生在BEGIN块执行之前的：</p>
<div class="highlight"><pre><span></span><code>$ <span class="nb">echo</span> <span class="p">|</span> awk -v <span class="nv">key1</span><span class="o">=</span>V1 -v <span class="nv">key2</span><span class="o">=</span>value2 <span class="s1">&#39;{print key1,key2}&#39;</span>
V1 value2
$ 
</code></pre></div>

<p>如果是多个变量，则使用 -v 多次。  </p>
<p>如果把上面两个方法合起来：</p>
<div class="highlight"><pre><span></span><code>$ <span class="nb">echo</span> <span class="p">|</span> awk -v <span class="nv">key1</span><span class="o">=</span>v1 -v <span class="nv">key2</span><span class="o">=</span>v2 <span class="s1">&#39;BEGIN{print &quot;BEGIN: &quot;key1,key2}{print &quot;ACTION: &quot;key1,key2}&#39;</span> <span class="nv">key1</span><span class="o">=</span>VALUE1 <span class="nv">key2</span><span class="o">=</span>VALUE2      
BEGIN: v1 v2
ACTION: VALUE1 VALUE2
$  
</code></pre></div>

<p>先是 -v 进行赋值，然后BEGIN块执行。之后是最后的变量赋值，如果有同名的就替换值，之后再逐行执行。打印出来的就是之后改变的值。  </p>
<h4 id="da-yin-huan-jing-bian-liang"><a class="toclink" href="#da-yin-huan-jing-bian-liang">打印环境变量</a></h4>
<p><em>最好的方法在后一小节。这里的方法也是可行的，但是可读性不好。</em><br>
写这段是为了理解一下命令参数解析的过程，以及一些特殊情况的处理。<br>
要直接打印环境变量是这样的：</p>
<div class="highlight"><pre><span></span><code>$ <span class="nb">echo</span> <span class="p">|</span> awk  <span class="s1">&#39;{print &quot;&#39;</span><span class="s2">&quot;</span><span class="nv">$PATH</span><span class="s2">&quot;</span><span class="s1">&#39;&quot;}&#39;</span>
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
$ 
</code></pre></div>

<p>这里的显示不明显，两边都是一对双引号套一个单引号。  </p>
<p><strong>解释说明</strong><br>
先用一个简单点的环境变量来举例：</p>
<div class="highlight"><pre><span></span><code>$ <span class="nb">echo</span> <span class="nv">$USER</span>
root
$ 
</code></pre></div>

<p>这个没有什么空格换特殊字符，这样可以去掉最里面的一对双引号：</p>
<div class="highlight"><pre><span></span><code>$ <span class="nb">echo</span> <span class="p">|</span> awk  <span class="s1">&#39;{print &quot;&#39;</span><span class="nv">$USER</span><span class="s1">&#39;&quot;}&#39;</span>  
root
$ 
</code></pre></div>

<p>这里成对出现了2对单引号，所以就被分成了这样两个部分：<code>'{print "'</code> 和 <code>'"}'</code>。awk对2个单引号内的命令起作用。<br>
剩下的就是  <code>$USER</code> 了，这个最早就被 shell 给处理替换了。<br>
在变量本身被shell处理完之后，如果有空格之类的，有会被认为不是一个部分。这里就再用双引号把环境变量的值包起来，将值作为整体的一个域。  </p>
<p><strong>我的理解</strong><br>
最外层的引号是用来界定字符边界的，但是只要是连续的就被系统认为是一串（一个域）。可以用多对引号把多个字符串引起来，但是每对引号之间不要出现分隔符。这样，最后解析交给命令处理的还是一个整体的字符串（一个域）。<br>
下面是用echo命令的演示：</p>
<div class="highlight"><pre><span></span><code>$ <span class="nb">echo</span> <span class="s1">&#39;abc&#39;&#39;def&#39;</span>
abcdef
$ <span class="nb">echo</span> <span class="s1">&#39;abc&#39;</span><span class="nv">$USER</span><span class="s1">&#39;def&#39;</span>
abcrootdef
$ <span class="nb">echo</span> <span class="s1">&#39;abc &#39;</span><span class="nv">$USER</span><span class="s1">&#39; def&#39;</span>
abc root def
$ 
</code></pre></div>

<p>加上for循环再演示一次：</p>
<div class="highlight"><pre><span></span><code>$ <span class="nv">HELLO</span><span class="o">=</span><span class="s1">&#39;Hello World !&#39;</span>
$ <span class="k">for</span> i <span class="k">in</span> <span class="nv">$HELLO</span><span class="p">;</span> <span class="k">do</span> <span class="nb">echo</span> <span class="nv">$i</span><span class="p">;</span><span class="k">done</span>
Hello
World
!
$ <span class="k">for</span> i <span class="k">in</span> <span class="s1">&#39;BEFOR&#39;</span><span class="nv">$HELLO</span><span class="s1">&#39;AFTER&#39;</span><span class="p">;</span> <span class="k">do</span> <span class="nb">echo</span> <span class="nv">$i</span><span class="p">;</span><span class="k">done</span>
BEFORHello
World
!AFTER
$ <span class="k">for</span> i <span class="k">in</span> <span class="s1">&#39;BEFOR&#39;</span><span class="s2">&quot;</span><span class="nv">$HELLO</span><span class="s2">&quot;</span><span class="s1">&#39;AFTER&#39;</span><span class="p">;</span> <span class="k">do</span> <span class="nb">echo</span> <span class="nv">$i</span><span class="p">;</span><span class="k">done</span>
BEFORHello World !AFTER
$ 
</code></pre></div>

<p><em>最外层的引号仅仅是界定边界的，用多对引号但是所有内容都相连，也被认为是一个域。</em>  </p>
<p>虽然有多对引号，但是所有内容都是相连的，没有分隔符，最后交给命令处理的还是一个域。<br>
这样做的好处就是，用了单引号，但是把需要shell解析的部分放到了单引号的外面，这样shell还是可以正常解析。<br>
为了保证环境变量解析完之后依然是一个域，需要用双引号引起来。<br>
再来就是awk中接着print的双引号了。awk中的引号不是界定边界的而是区分是变量还是字符串的。没有双引号的话表示这个内容是变量，用双引号引起来表示里面的内容是字符串，直接打印。  </p>
<p><strong>其他写法</strong><br>
下面两种写法也能实现同样的效果，帮助理解吧：</p>
<div class="highlight"><pre><span></span><code>$ <span class="nb">echo</span> <span class="p">|</span> awk <span class="s2">&quot;{print \&quot;</span><span class="nv">$PATH</span><span class="s2">\&quot;}&quot;</span>
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
$ <span class="nb">echo</span> <span class="p">|</span> awk <span class="se">\{</span>print<span class="se">\&quot;</span><span class="s2">&quot;</span><span class="nv">$PATH</span><span class="s2">&quot;</span><span class="se">\&quot;\}</span>
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
$ 
</code></pre></div>

<p>awk命令还是尽量用单引号引起来，防止shell对其中内容进行解释。就是第一种办法就最好的。  </p>
<h4 id="yin-yong-ming-ling-xing-ding-yi-de-bian-liang"><a class="toclink" href="#yin-yong-ming-ling-xing-ding-yi-de-bian-liang">引用命令行定义的变量</a></h4>
<p>最开始的3种方法，有2种是在引号外完成变量定义的，这样就不会对shell进行干扰：</p>
<div class="highlight"><pre><span></span><code>$ <span class="nb">echo</span> <span class="p">|</span> awk <span class="s1">&#39;{print path}&#39;</span> <span class="nv">path</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$PATH</span><span class="s2">&quot;</span>
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
$ <span class="nb">echo</span> <span class="p">|</span> awk -v <span class="nv">path</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$PATH</span><span class="s2">&quot;</span> <span class="s1">&#39;{print path}&#39;</span>                                            
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
$ 
</code></pre></div>

<p>先是用命令行的方式把环境变量赋值给自定义变量，这个操作在引号外。然后再引号里面直接用自定义变量就好了。<br>
如果是在BEGIN块中要这么做，就参考上以小节的做法。  </p>
<h3 id="awk-jin-jie"><a class="toclink" href="#awk-jin-jie">awk 进阶</a></h3>
<p>从free命令同获取当前内存使用数值：</p>
<div class="highlight"><pre><span></span><code>$ free <span class="p">|</span> awk <span class="s1">&#39;/^Mem:/ {print $3}&#39;</span>
<span class="m">335840</span>
$ 
</code></pre></div>

<p>这里用的是正则匹配。不过awk还有其他的一些语法，可以做到更加精确的匹配。  </p>
<h4 id="tiao-jian-xian-zhi"><a class="toclink" href="#tiao-jian-xian-zhi">条件限制</a></h4>
<p>限制第一个字段值来匹配：</p>
<div class="highlight"><pre><span></span><code>$ free <span class="p">|</span> awk <span class="s1">&#39;$1 == &quot;Mem:&quot; {print $3}&#39;</span>
<span class="m">335744</span>
$
</code></pre></div>

<p>限制要第几行的数据：</p>
<div class="highlight"><pre><span></span><code>$ free <span class="p">|</span> awk <span class="s1">&#39;NR == 2 {print $3}&#39;</span>        
<span class="m">335796</span>
$ 
</code></pre></div>

<h4 id="tiao-jian-yu-ju"><a class="toclink" href="#tiao-jian-yu-ju">条件语句</a></h4>
<p>awk 也提供了 if, else, while 等这些条件语句，不过似乎用不了那么深，举一个if的例子。<br>
同样是限制第几行，这里通过if语句来判断：</p>
<div class="highlight"><pre><span></span><code>$ free <span class="p">|</span> awk <span class="s1">&#39;{if(NR == 2) print $3}&#39;</span>             
<span class="m">335740</span>
$ 
</code></pre></div>

<h4 id="zheng-ze-pi-pei"><a class="toclink" href="#zheng-ze-pi-pei">正则匹配</a></h4>
<p>~是匹配正则表达式的运算符。另外，~!是不匹配正则表达式的运算符。<br>
匹配第一个字段：</p>
<div class="highlight"><pre><span></span><code>$ free <span class="p">|</span> awk <span class="s1">&#39;$1 ~ /Mem/ {print $3}&#39;</span>
<span class="m">335844</span>
$ 
</code></pre></div>

<p>关于正则还有一个内置变量是 IGNORECASE，如果设置为1，可以忽略大小写：</p>
<div class="highlight"><pre><span></span><code>$ free <span class="p">|</span> awk <span class="s1">&#39;$1 ~ &quot;mem&quot;  {print $3}&#39;</span> <span class="nv">IGNORECASE</span><span class="o">=</span><span class="m">1</span>
<span class="m">335708</span>
$ 
</code></pre></div>

<p>为变量赋值的方法之前讲过了，有好几种方式。  </p>
<h4 id="da-yin-jiu-jiu-cheng-fa-biao"><a class="toclink" href="#da-yin-jiu-jiu-cheng-fa-biao">打印九九乘法表</a></h4>
<p>这个很高端的样子，就贴在最后了：</p>
<div class="highlight"><pre><span></span><code>$ seq <span class="m">9</span> <span class="p">|</span> sed <span class="s1">&#39;H;g&#39;</span> <span class="p">|</span> awk -v <span class="nv">RS</span><span class="o">=</span><span class="s1">&#39;&#39;</span> <span class="s1">&#39;{for(i=1;i&lt;=NF;i++)printf(&quot;%dx%d=%d%s&quot;, i, NR, i*NR, i==NR?&quot;\n&quot;:&quot;\t&quot;)}&#39;</span>
<span class="nv">1x1</span><span class="o">=</span><span class="m">1</span>
<span class="nv">1x2</span><span class="o">=</span><span class="m">2</span>   <span class="nv">2x2</span><span class="o">=</span><span class="m">4</span>
<span class="nv">1x3</span><span class="o">=</span><span class="m">3</span>   <span class="nv">2x3</span><span class="o">=</span><span class="m">6</span>   <span class="nv">3x3</span><span class="o">=</span><span class="m">9</span>
<span class="nv">1x4</span><span class="o">=</span><span class="m">4</span>   <span class="nv">2x4</span><span class="o">=</span><span class="m">8</span>   <span class="nv">3x4</span><span class="o">=</span><span class="m">12</span>  <span class="nv">4x4</span><span class="o">=</span><span class="m">16</span>
<span class="nv">1x5</span><span class="o">=</span><span class="m">5</span>   <span class="nv">2x5</span><span class="o">=</span><span class="m">10</span>  <span class="nv">3x5</span><span class="o">=</span><span class="m">15</span>  <span class="nv">4x5</span><span class="o">=</span><span class="m">20</span>  <span class="nv">5x5</span><span class="o">=</span><span class="m">25</span>
<span class="nv">1x6</span><span class="o">=</span><span class="m">6</span>   <span class="nv">2x6</span><span class="o">=</span><span class="m">12</span>  <span class="nv">3x6</span><span class="o">=</span><span class="m">18</span>  <span class="nv">4x6</span><span class="o">=</span><span class="m">24</span>  <span class="nv">5x6</span><span class="o">=</span><span class="m">30</span>  <span class="nv">6x6</span><span class="o">=</span><span class="m">36</span>
<span class="nv">1x7</span><span class="o">=</span><span class="m">7</span>   <span class="nv">2x7</span><span class="o">=</span><span class="m">14</span>  <span class="nv">3x7</span><span class="o">=</span><span class="m">21</span>  <span class="nv">4x7</span><span class="o">=</span><span class="m">28</span>  <span class="nv">5x7</span><span class="o">=</span><span class="m">35</span>  <span class="nv">6x7</span><span class="o">=</span><span class="m">42</span>  <span class="nv">7x7</span><span class="o">=</span><span class="m">49</span>
<span class="nv">1x8</span><span class="o">=</span><span class="m">8</span>   <span class="nv">2x8</span><span class="o">=</span><span class="m">16</span>  <span class="nv">3x8</span><span class="o">=</span><span class="m">24</span>  <span class="nv">4x8</span><span class="o">=</span><span class="m">32</span>  <span class="nv">5x8</span><span class="o">=</span><span class="m">40</span>  <span class="nv">6x8</span><span class="o">=</span><span class="m">48</span>  <span class="nv">7x8</span><span class="o">=</span><span class="m">56</span>  <span class="nv">8x8</span><span class="o">=</span><span class="m">64</span>
<span class="nv">1x9</span><span class="o">=</span><span class="m">9</span>   <span class="nv">2x9</span><span class="o">=</span><span class="m">18</span>  <span class="nv">3x9</span><span class="o">=</span><span class="m">27</span>  <span class="nv">4x9</span><span class="o">=</span><span class="m">36</span>  <span class="nv">5x9</span><span class="o">=</span><span class="m">45</span>  <span class="nv">6x9</span><span class="o">=</span><span class="m">54</span>  <span class="nv">7x9</span><span class="o">=</span><span class="m">63</span>  <span class="nv">8x9</span><span class="o">=</span><span class="m">72</span>  <span class="nv">9x9</span><span class="o">=</span><span class="m">81</span>
$ 
</code></pre></div>

<h3 id="zabbix-zi-ding-yi-can-shu-jian-kong-xiang"><a class="toclink" href="#zabbix-zi-ding-yi-can-shu-jian-kong-xiang">Zabbix 自定义参数（监控项）</a></h3>
<p>用户自定义参数可以通过Zabbix agent执行非Zabbix原生的agent监控项。只要你有办法能通过命令获取到要监控的指标。  </p>
<h4 id="pei-zhi-wen-jian"><a class="toclink" href="#pei-zhi-wen-jian">配置文件</a></h4>
<p>可以直接在配置文件 zabbix_agentd.conf 中定义 UserParameter。  </p>
<div class="highlight"><pre><span></span><code><span class="c1">### Option: HostnameItem</span><span class="w"></span>
<span class="c1">#       Item used for generating Hostname if it is undefined. Ignored if Hostname is defined.</span><span class="w"></span>
<span class="c1">#       Does not support UserParameters or aliases.</span><span class="w"></span>
<span class="c1">#</span><span class="w"></span>
<span class="c1"># Mandatory: no</span><span class="w"></span>
<span class="c1"># Default:</span><span class="w"></span>
<span class="c1"># HostnameItem=system.hostname</span><span class="w"></span>
</code></pre></div>

<p><strong>Include配置</strong><br>
虽然直接写在这下面就可以了，不过配置文件还有一个Include的配置：</p>
<div class="highlight"><pre><span></span><code><span class="c1">### Option: Include</span><span class="w"></span>
<span class="c1">#       You may include individual files or all files in a directory in the configuration file.</span><span class="w"></span>
<span class="c1">#       Installing Zabbix will create include directory in /usr/local/etc, unless modified during the compile time.</span><span class="w"></span>
<span class="c1">#</span><span class="w"></span>
<span class="c1"># Mandatory: no</span><span class="w"></span>
<span class="c1"># Default:</span><span class="w"></span>
<span class="c1"># Include=</span><span class="w"></span>

<span class="na">Include</span><span class="o">=</span><span class="s">/etc/zabbix/zabbix_agentd.d/*.conf</span><span class="w"></span>

<span class="c1"># Include=/usr/local/etc/zabbix_agentd.userparams.conf</span><span class="w"></span>
<span class="c1"># Include=/usr/local/etc/zabbix_agentd.conf.d/</span><span class="w"></span>
<span class="c1"># Include=/usr/local/etc/zabbix_agentd.conf.d/*.conf</span><span class="w"></span>
</code></pre></div>

<p>建议把这些配置分下类，创建独立的 zabbix_agentd.d/*.conf 文件，方便管理。</p>
<h4 id="yu-fa"><a class="toclink" href="#yu-fa">语法</a></h4>
<p>自定义参数的语法如下：</p>
<div class="highlight"><pre><span></span><code>UserParameter=&lt;key&gt;,&lt;command&gt;
</code></pre></div>

<p>key，就是监控项用的key。必须全局唯一。<br>
<strong>命名要求：</strong>只能使用字母、数字、下划线、中横杠、点号。即 <code>0-9a-zA-Z_-.</code> 这些字符。  </p>
<p>比如下面的文件中定义了3个通过free命令获取值的监控项：</p>
<div class="highlight"><pre><span></span><code>$ cat /etc/zabbix/zabbix_agentd.d/os.conf
<span class="nv">UserParameter</span><span class="o">=</span>os.memory.total, free -m <span class="p">|</span> awk <span class="s1">&#39;$1==&quot;Mem:&quot; {print $2}&#39;</span>
<span class="nv">UserParameter</span><span class="o">=</span>os.memory.used, free -m <span class="p">|</span> awk <span class="s1">&#39;$1==&quot;Mem:&quot; {print $3}&#39;</span>
<span class="nv">UserParameter</span><span class="o">=</span>os.memory.free, free -m <span class="p">|</span> awk <span class="s1">&#39;$1==&quot;Mem:&quot; {print $4}&#39;</span>
</code></pre></div>

<p>具体一步步如何实现的，参考下一小节。  </p>
<h4 id="tiao-shi-bu-zhou"><a class="toclink" href="#tiao-shi-bu-zhou">调试步骤</a></h4>
<p>自定义参数，一步步实现的操作过程。  </p>
<h5 id="di-yi-bu-xie-yi-ge-ming-ling-huo-jiao-ben"><a class="toclink" href="#di-yi-bu-xie-yi-ge-ming-ling-huo-jiao-ben">第一步：写一个命令或脚本</a></h5>
<p>能够成功的在命令行中把值打印出来：</p>
<div class="highlight"><pre><span></span><code>$ free -m <span class="p">|</span> awk <span class="s1">&#39;$1==&quot;Mem:&quot; {print $3}&#39;</span> 
<span class="m">569</span>
$ 
</code></pre></div>

<p>由于zabbix是使用zabbix账号执行的，有些命令有可能zabbix无权限。所以可以加上sudo指定zabbix用户执行再验证一下：</p>
<div class="highlight"><pre><span></span><code>$ sudo -u zabbix free -m <span class="p">|</span> awk <span class="s1">&#39;$1==&quot;Mem:&quot; {print $3}&#39;</span>
<span class="m">571</span>
$ 
</code></pre></div>

<h5 id="di-er-bu-tian-jia-dao-pei-zhi-wen-jian-zhong"><a class="toclink" href="#di-er-bu-tian-jia-dao-pei-zhi-wen-jian-zhong">第二步：添加到配置文件中</a></h5>
<div class="highlight"><pre><span></span><code>UserParameter=os.memory.used, free -m | awk &#39;$1==&quot;Mem:&quot; {print $3}&#39;
</code></pre></div>

<h5 id="di-san-bu-ce-shi-key"><a class="toclink" href="#di-san-bu-ce-shi-key">第三步：测试key</a></h5>
<p>使用 zabbix_agentd 并且用 -t 选项指定key来进行测试：</p>
<div class="highlight"><pre><span></span><code>$ zabbix_agentd -t os.memory.used
os.memory.used                                <span class="o">[</span>t<span class="p">|</span><span class="m">571</span><span class="o">]</span>
$ 
</code></pre></div>

<p>测试成功说明写的没问题。  </p>
<h5 id="di-si-bu-chong-qi-agent"><a class="toclink" href="#di-si-bu-chong-qi-agent">第四步：重启agent</a></h5>
<p>要重启agent才能使新的配置文件生效：</p>
<div class="highlight"><pre><span></span><code>$ systemctl restart zabbix-agent
$
</code></pre></div>

<p>之后就可以去Web添加监控项了。  </p>
<h4 id="dai-can-shu-de-yong-fa"><a class="toclink" href="#dai-can-shu-de-yong-fa">带参数的用法</a></h4>
<p>可以为key设置参数，这样一个设置可以应对多个监控项。<br>
语法如下：</p>
<div class="highlight"><pre><span></span><code>UserParameter=key[*],command
</code></pre></div>

<p>这里的星号表示可以带任意数量的参数，并且似乎也只有这一种用法，没有指定参数数量的写法。  </p>
<h5 id="zai-command-zhong-shi-yong-can-shu"><a class="toclink" href="#zai-command-zhong-shi-yong-can-shu">在command中使用参数</a></h5>
<p>在command中使用位置引用$1......$9，来引用key中相应的参数。<br>
另外$0表示命令本身。  </p>
<h6 id="guan-yu-fu-hao"><a class="toclink" href="#guan-yu-fu-hao">关于$符号</a></h6>
<p>由于$1.....$9有了特殊的意义，在awk中的$1也会被zabbix先替换掉。这时应该使用$$1。<br>
zabbix仅仅只替换位置参数，对于单独的$符号或者其他组合（比如$NF）,zabbix不会处理。<br>
zabbix仅仅只在使用了key[*]，这样指定了key是带参数的时候才会进行位置参数替换的处理。所以之前的示例使用$1没有问题。  </p>
<h5 id="xiu-gai-wei-dai-can-shu-de-key"><a class="toclink" href="#xiu-gai-wei-dai-can-shu-de-key">修改为带参数的key</a></h5>
<p>现在把之前的示例改成一种更灵活的设置方式：</p>
<div class="highlight"><pre><span></span><code>UserParameter=os.free[*], free -m | awk &#39;$$1~NAME {print $$(COLUMN+1)}&#39; IGNORECASE=1 NAME=&quot;$1&quot; COLUMN=$2
</code></pre></div>

<p>测试效果如下：</p>
<div class="highlight"><pre><span></span><code>$ zabbix_agentd -t os.free<span class="o">[</span>mem,2<span class="o">]</span>
os.free<span class="o">[</span>mem,2<span class="o">]</span>                                <span class="o">[</span>t<span class="p">|</span><span class="m">570</span><span class="o">]</span>
$ 
</code></pre></div>

<h4 id="shi-li"><a class="toclink" href="#shi-li">示例</a></h4>
<p>一些自定义参数的示例：</p>
<div class="highlight"><pre><span></span><code>UserParameter=Nginx.active[*], /usr/bin/curl -s &quot;http://$1:$2/status&quot; | awk &#39;/^Active/ {print $NF}&#39;
UserParameter=Nginx.reading[*], /usr/bin/curl -s &quot;http://$1:$2/status&quot; | grep &#39;Reading&#39; | cut -d&quot; &quot; -f2
UserParameter=Nginx.writing[*], /usr/bin/curl -s &quot;http://$1:$2/status&quot; | grep &#39;Writing&#39; | cut -d&quot; &quot; -f4
UserParameter=Nginx.waiting[*], /usr/bin/curl -s &quot;http://$1:$2/status&quot; | grep &#39;Waiting&#39; | cut -d&quot; &quot; -f6
UserParameter=Nginx.accepted[*], /usr/bin/curl -s &quot;http://$1:$2/status&quot; | awk &#39;/^([ \t]+[0-9]+){3}/ {print $$1}&#39;
UserParameter=Nginx.handled[*], /usr/bin/curl -s &quot;http://$1:$2/status&quot; | awk &#39;/^([ \t]+[0-9]+){3}/ {print $$2}&#39;
UserParameter=Nginx.requests[*], /usr/bin/curl -s &quot;http://$1:$2/status&quot; | awk &#39;/^([ \t]+[0-9]+){3}/ {print $$3}&#39;

UserParameter=os.free[*], free | awk &#39;$$1~NAME {print $$(COLUMN+1)}&#39; IGNORECASE=1 NAME=&quot;$1&quot; COLUMN=$2

UserParameter=Mysql.dml[*] -h$1 -u$2 -p$3 -e &#39;SHOW GLOBAL STATUS&#39; | awk &#39;/^Com_$4\&gt;/ {print $$2}&#39;
</code></pre></div>

<h5 id="zheng-ze-biao-da-shi-ci-wei-mao-ding"><a class="toclink" href="#zheng-ze-biao-da-shi-ci-wei-mao-ding">正则表达式 词尾锚定</a></h5>
<p>在调试mysql的时候，遇到一些问题。正则表达式匹配不够精确，有多个值：</p>
<div class="highlight"><pre><span></span><code>$ mysql -e <span class="s1">&#39;SHOW GLOBAL STATUS&#39;</span> <span class="p">|</span> awk <span class="s1">&#39;/^Com_select/ {print $0}&#39;</span>       
Com_select      <span class="m">67679</span>
$ mysql -e <span class="s1">&#39;SHOW GLOBAL STATUS&#39;</span> <span class="p">|</span> awk <span class="s1">&#39;/^Com_update/ {print $0}&#39;</span>       
Com_update      <span class="m">1098</span>
Com_update_multi        <span class="m">0</span>
$ mysql -e <span class="s1">&#39;SHOW GLOBAL STATUS&#39;</span> <span class="p">|</span> awk <span class="s1">&#39;/^Com_delete/ {print $0}&#39;</span>       
Com_delete      <span class="m">678</span>
Com_delete_multi        <span class="m">0</span>
$ mysql -e <span class="s1">&#39;SHOW GLOBAL STATUS&#39;</span> <span class="p">|</span> awk <span class="s1">&#39;/^Com_insert/ {print $0}&#39;</span>       
Com_insert      <span class="m">38494</span>
Com_insert_select       <span class="m">0</span>
$ 
</code></pre></div>

<p>这里是加了词尾锚定：</p>
<div class="highlight"><pre><span></span><code>$ mysql -e <span class="s1">&#39;SHOW GLOBAL STATUS&#39;</span> <span class="p">|</span> awk <span class="s1">&#39;/^Com_delete\&gt;/ {print $0}&#39;</span>  
Com_delete      <span class="m">708</span>
$ 
</code></pre></div>

<p>词尾锚定是 \&gt;，顺便词首就是 \&lt;。</p>
<p>其实也没那么复杂，还有很多办法：</p>
<div class="highlight"><pre><span></span><code>$ mysql -e <span class="s1">&#39;SHOW GLOBAL STATUS&#39;</span> <span class="p">|</span> awk <span class="s1">&#39;/^Com_delete[&quot; &quot;\t]/ {print $0}&#39;</span>   
Com_delete      <span class="m">712</span>
$ mysql -e <span class="s1">&#39;SHOW GLOBAL STATUS&#39;</span> <span class="p">|</span> awk <span class="s1">&#39;/^Com_delete[^_]/ {print $0}&#39;</span>      
Com_delete      <span class="m">715</span>
$ mysql -e <span class="s1">&#39;SHOW GLOBAL STATUS&#39;</span> <span class="p">|</span> awk <span class="s1">&#39;$1 == &quot;Com_delete&quot; {print $0}&#39;</span> 
Com_delete      <span class="m">717</span>
$
</code></pre></div>

<h4 id="systemrun"><a class="toclink" href="#systemrun">system.run</a></h4>
<p>这个是zabbix内置key，也能够实现同样的功能，那么到底用哪个好？  </p>
<h5 id="nei-zhi-key-systemrun"><a class="toclink" href="#nei-zhi-key-systemrun">内置key system.run</a></h5>
<p>这是一个内置key:</p>
<div class="highlight"><pre><span></span><code>system.run[command,&lt;mode&gt;]
</code></pre></div>

<p>在主机上指定的命令的执行。返回命令执行结果的文本值。如果指定NOWAIT的模式，这将返回执行命令的结果为1。  </p>
<ul>
<li>command: 命令</li>
<li>mode: wait (默认值, 执行超时时间), nowait (不等待)</li>
<li>最大可用返回512KB数据，包含空白数据。命令输出数据必须是文本</li>
</ul>
<p>默认agent不支持，安全隐患还是很大的。需要agent端开启RemoteCommand，允许远程执行命令。  </p>
<h5 id="you-lie-bi-jiao"><a class="toclink" href="#you-lie-bi-jiao">优劣比较</a></h5>
<p>通过这个也能实现自定义监控功能，而且不用去agent上定义UserParameter。直接在web就能完成全部操作。这个可能是好处。<br>
用UserParameter，如果agent多，需要每一台agent上都去设置UserParameter，这就很烦。不过还有自动化运维工具可以解决批量更新、操作文件的问题。  </p>
<h5 id="bu-tui-jian-shi-yong"><a class="toclink" href="#bu-tui-jian-shi-yong">不推荐使用</a></h5>
<p>一方面是安全隐患，所以这个功能默认是关闭的。<br>
如果开启，使用Web服务就能通过这个key让agent执行任意命令了。虽然这里还会受到agent端zabbix账号的命令权限的限制。但是很多情况下可能都会为了方便，直接sudo就有了高权限。<br>
另一方面是丑。命令全写在key的参数里可能会很长。使用自定义参数，可以自定义key的值，让key值简短一些，并且表达式看起来也更漂亮。  </p>
<p>一个求助 system.run 使用问题的帖子，在问题解决后解答者给的最后的回复：  </p>
<blockquote>
<p>Cool, one more hint: UserParameteres, this could shorten your keys and make the expressions look prettier</p>
</blockquote>
      </div>
      <div class="back-to-top">
        <a href="/">HOME</a>
        <a href="#top">TOP</a>
      </div>
    </article>
  </div>
<!-- end article -->
<!-- 页面往下滚动一段之后才会显示TOC -->
<script>
  window.onscroll = function() {
    var tocbox = document.getElementsByClassName('toc')[0];
    var osTop = document.documentElement.scrollTop || document.body.scrollTop;
    var osWidth = document.documentElement.scrollWidth || document.body.scrollWidth;
    // console.log(osTop)
    if (osTop>300 && osWidth>865) {
      tocbox.style.display = "block"
    }
    if (osTop<300 || osWidth<865) {
      tocbox.style.display = "none"
    }
  }
</script>
                <footer>
                    <div class="icons">
                    </div>
                    <span id="busuanzi_container_page_pv" style="padding: 10px">本文阅读量<span id="busuanzi_value_page_pv"></span>次</span>
                    <span id="busuanzi_container_site_pv" style="padding: 10px">本站总访问量<span id="busuanzi_value_site_pv"></span>次</span>
                    <span id="busuanzi_container_site_uv" style="padding: 10px">本站总访客数<span id="busuanzi_value_site_uv"></span>人</span>
                    <p>© <script>document.write(moment().format('YYYY'));</script> 749B</p>
                </footer>
        </div>
</body>
</html>